/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package sms4j.listener;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import sms4j.config.Config;
import sms4j.util.SmsUtil;

/**
 *
 * @author Swang
 */
public class SocketMessageListenerThread extends Thread{

    private static final Log log = LogFactory.getLog(SocketMessageListenerThread.class);
    private int listenPort = Config.SOCKET_MESSAGE_LISTENER_PORT;
    private String allowIPPattern = Config.SOCKET_CLIENT_ALLOW_IP_PATTERN;
    private ServerSocket server = null;
    private static SocketMessageListenerThread instance = null;
    @Override
    public void run() {
        acceptConnections();
    }

    public static SocketMessageListenerThread getInstance() {
        if(null == instance) {
            instance = new SocketMessageListenerThread();
        }
        return instance;
    }

    /**
     * 监听Socket连接
     */
    public void acceptConnections() {
        try {
            server = new ServerSocket(listenPort);
            log.info("Listener on the port " + listenPort);
            Socket incomingConnection = null;
            while (true) {
                incomingConnection = server.accept();
                handleConnection(incomingConnection);
            }
        } catch (BindException e) {
            log.error("Unable to bind to port: " + listenPort, e);
        } catch (IOException e) {
            log.error("Unable to instantiate a ServerSocket on port: " + listenPort, e);
        }
    }

    public void closeServiceSocket() {
        if (server != null) {
            try {
                server.close();
            } catch (IOException ex) {
                log.error("CloseServiceSocket Exception ", ex);
            }
            server = null;
        }
    }

    /**
     * 处理Socket连接
     * @param incomingConnection 
     */
    private void handleConnection(Socket incomingConnection) {
        String clientIp = incomingConnection.getInetAddress().getHostAddress();
        PrintWriter printWriter = null;
        BufferedReader streamReader = null;
        try {
            OutputStream outputToSocket = incomingConnection.getOutputStream();
            InputStream inputFromSocket = incomingConnection.getInputStream();
            streamReader = new BufferedReader(new InputStreamReader(inputFromSocket,Config.SOCKET_INPUTSTREAM_ENCODE));
            printWriter = new PrintWriter(outputToSocket);
            //检查IP
            if (!this.checkIP(clientIp)) {
                log.info("Refuse socket connection: " + clientIp);
                printWriter.println("IP is invalid!");
                printWriter.flush();
                return;
            }
            log.info("Handle socket connection: " + clientIp);

            StringBuilder jsondata = new StringBuilder();
            String line = null;
            while (!(line = streamReader.readLine()).equalsIgnoreCase("EOF")) {
                jsondata.append(line);
            }
            log.info("Send Message: jsonData->"+jsondata.toString());
            String result = SmsUtil.sendMessage(jsondata.toString());
            printWriter.println(result);
            printWriter.flush();

        } catch (Exception e) {
            log.error("Error handling a client connection: ", e);
        } finally {
            if (null != printWriter) {
                printWriter.close();
                printWriter = null;
            }
            if (null != streamReader) {
                try {
                    streamReader.close();
                } catch (IOException ex) {
                    log.error("Error close streamReader: ", ex);
                }
                streamReader = null;
            }
            if (null != incomingConnection) {
                try {
                    incomingConnection.close();
                } catch (IOException ex) {
                    log.error("Error close incomingConnection: ", ex);
                }
                incomingConnection = null;
            }
        }
    }

    private boolean checkIP(String src) {
        if (allowIPPattern == null || allowIPPattern.trim().equals("")) {
            return true;
        }
        String[] allowIPArray = allowIPPattern.split(";");
        for (String allowIP : allowIPArray) {
            if (src.equalsIgnoreCase(allowIP)) {
                return true;
            }
            if (allowIP.indexOf("*") != -1) {
                //IP范围
                String allowIPPrefix = allowIP.substring(0, allowIP.indexOf("*"));
                if (src.startsWith(allowIPPrefix)) {
                    return true;
                }
            }
        }
        return false;
    }

    public static void main(String[] args) {
        System.out.println(SocketMessageListenerThread.getInstance().checkIP("localhost"));

    }
}
